"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const pkg_1 = require("./utils/pkg");
const fs = require("fs");
const fse = require("fs-extra");
const path = require("path");
const ora = require("ora");
const prettier = require("prettier");
const inquirer = require("inquirer");
const chalk = require("chalk");
const log = console.log;
const cwd = process.cwd();
let projectPath;
let dirName;
const { program } = require("commander");
const execa = require("execa");
program.version("0.0.1").description("一个脚手架工具");
program
    .command("init <name>")
    .description("init project")
    .action((name) => {
    try {
        if (fs.existsSync(path.join(cwd, name))) {
            throw new Error("文件夹已存在");
        }
        dirName = name;
        projectPath = path.join(cwd, name);
    }
    catch (error) {
        log(chalk.red(error.message));
        process.exit(0);
    }
    let config = {
        name: "",
        framework: "",
        useBabel: true,
        useWebpack: true,
        libraries: [],
        css: [],
        manager: "",
        ready: false,
    };
    inquirer
        .prompt([
        {
            type: "input",
            name: "name",
            message: "project name",
            validate: function (input) {
                const done = this.async();
                const name = input.trim();
                if (!name.length) {
                    done("name is required");
                    return;
                }
                if (/^-/.test(name) || /-$/.test(name) || !/^[a-z\-]+$/.test(name)) {
                    done("name is invalid");
                    return;
                }
                done(null, true);
            },
        },
        {
            type: "list",
            name: "framework",
            choices: ["react"],
            message: "which framework",
            default: 0,
        },
        {
            type: "checkbox",
            name: "libraries",
            choices: ["react-router-dom", "react-redux"],
            when: function (answers) {
                if (answers.framework === "react") {
                    return true;
                }
                return false;
            },
        },
        {
            type: "checkbox",
            name: "css",
            message: "which css pre-processor?",
            choices: ["sass", "less"],
            default: 1,
        },
        {
            type: "list",
            name: "manager",
            message: "which package manager?",
            choices: ["npm", "yarn", "cnpm", "pnpm"],
            default: 0,
        },
        {
            type: "confirm",
            name: "ready",
            message: "Are you ready?",
        },
    ])
        .then(function (initConfig) {
        return __awaiter(this, void 0, void 0, function* () {
            const answers = Object.assign({}, config, initConfig);
            if (!answers.ready)
                return;
            fs.mkdirSync(name);
            const spinner = ora("init package.json");
            spinner.start();
            const install_spinner = ora("install packages");
            try {
                pkg_1.default.instance.name = answers.name;
                if (answers.framework === "react") {
                    pkg_1.default.instance.injectPrompt("react");
                }
                answers.libraries.forEach((c) => {
                    pkg_1.default.instance.injectPrompt(c);
                });
                answers.css.forEach((c) => {
                    pkg_1.default.instance.injectPrompt(c);
                });
                if (answers.useBabel) {
                    pkg_1.default.instance.injectPrompt("babel");
                }
                if (answers.useWebpack) {
                    pkg_1.default.instance.injectPrompt("webpack");
                }
                // 复制模版
                fse.copySync(path.join(__dirname, `../templates/${answers.framework}-template`), projectPath, { overwrite: true });
                const templatePkg = require(path.join(__dirname, `../templates/${answers.framework}-template/package.json`));
                fs.writeFileSync(path.join(projectPath, "./package.json"), prettier.format(JSON.stringify(Object.assign(Object.assign({}, pkg_1.default.instance.toJSON()), templatePkg)), { parser: "json" }));
                spinner.succeed();
                // 安装依赖
                yield new Promise((resolve, reject) => {
                    const c = execa(`${answers.manager}`, require(path.join(__dirname, `./manager/${answers.manager}.js`)).install, { cwd: projectPath });
                    c.stdout.on("data", (buffer) => {
                        log(chalk.blue(buffer));
                    });
                    c.on("close", () => {
                        resolve();
                    });
                    c.on("exit", () => {
                        resolve();
                    });
                    c.catch((err) => {
                        reject(err);
                    });
                })
                    .then(() => {
                    install_spinner.succeed();
                    log(chalk.green("依赖安装完成!"));
                })
                    .catch((err) => {
                    log(chalk.red(err.message));
                    install_spinner.fail();
                });
                log(chalk.green("\n按照一下步骤开始开发吧\n"));
                log(chalk.green(` cd ${dirName} \n`));
                log(chalk.green(" npm run dev\n"));
                process.exit(0);
            }
            catch (error) {
                log(chalk.red(error.message));
                install_spinner.fail();
            }
        });
    });
});
program.parse(process.argv);
